

#include "BSP.h"
#include "log/log2.h"
#include <Utility.h>

#include <phApp_Init.h>
#include <phNfcLib_Int.h>
#include <phNfcLib_Initialization.h>

#include <Reader/Reader.h>
// #include "ReaderDesfire2.h"
#include "reader_mfdf.h"
#include "reader_key_store.h"
#include "config/config3.h"
#include "Reader/reader_samav3.h"
/*
读取AccessGrid 为 KG公司账户提供的苹果虚拟卡。

AccessGrid DESFire details:
https://coda.io/d/AccessGrid-DESFire-details_d2ygKEWhJ_q/AccessGrid-DESFire-details_suTg9UjT#_lunHi90F

Kogniza P1:
key 00: 767609ED9733AF6C20746230FB037D19
key 01: B858AB3AEA172CFD47BEDE63E833520A

*/

/*
AccessGrid has 2 common DESFire application structures:

1. Simple structure
2. Key diversified structure

Simple structure:
It contains a hex encoded value that follows this format:

1. First 3 bytes: 0’s (ex: 000000)
2. Next byte static value 02 
3. Next byte static value 01 
4. Next byte is number of bits in card data (ex: 1A aka 26 bits)
5. Everything after is card data (ex: 2AA455 )
6. The rest is padding to reach expected file size (see below)

All together: 

00000002011A2A303D0000000000000000000000000000000000000000000000

We have a TCI range, but for the passes you can provision the terminal capabilities identifier is 024D20 or 
020000 and the application ID is F56401 or 0164F5 depending on if you need big endian or little endian value.
*/


#pragma pack(push, 1)
typedef struct {
	uint8_t perfix[5];
	uint8_t nbits;
	uint8_t data[16]; // 16 bytes of data
} access_grid_simple_t ;
#pragma pack(pop)

// static const uint8_t keys[2][16] = {
// 	[0] = {
// 		0x76, 0x76, 0x09, 0xED, 0x97, 0x33, 0xAF, 0x6C,
// 		0x20, 0x74, 0x62, 0x30, 0xFB, 0x03, 0x7D, 0x19
// 	},

// 	[1] = {
// 		0xB8, 0x58, 0xAB, 0x3A, 0xEA, 0x17, 0x2C, 0xFD,
// 		0x47, 0xBE, 0xDE, 0x63, 0xE8, 0x33, 0x52, 0x0A
// 	}
// };

int reader_read_ag_kg(param_access_grid_t* param, credential_t* cred){
	int ret;
	key_set_t *key_set = &param->awc_read_key_set;
	uint8_t evid = reader_mfdf_get_evid(key_set->key_id); // Software ID
	if(evid == PHAL_MFDFEVX_SAMAV3_NONX_ID){
		//激活SAM AV3
		ret = samav3_activate2();
		if(ret){
			return 1;
		}
	}
	uint8_t keyNo = 1;
	uint8_t ver = 0;
	if(reader_ks_setup(key_set->key_id, &keyNo, &ver)){
		LOG2_ERR("reader_ks_setup fail");
		return 1;
	}
	
	void* key_store = phNfcLib_GetDataParams(PH_COMP_KEYSTORE);
//4. Diversify Credential application key using static UID from step 2.
//5. SELECT and authenticate Credential application using diversified key.
	// uint32_t aid = 0xF56401; // AccessGrid KG application AID
	ret = reader_mfdf_select_application(evid, PHAL_MFDFEVX_SELECT_PRIMARY_APP, key_set->aid, NULL);
	if(ret){
		uint32_t aid = 0;
		memcpy(&aid, key_set->aid, 3);
		LOG2_ERR("reader_mfdf_select_application(%06X) fail: %04X", aid, ret);
		return 4;
	}

	const uint8_t bKeyNoCard = key_set->key_no; // Key number on card, 0x01 for primary application
	ret = reader_mfdf_authenticate_aes(evid, PHAL_MFDFEVX_NO_DIVERSIFICATION, keyNo, ver, bKeyNoCard, NULL, 0);
	if(ret){
		LOG2_ERR("reader_mfdf_authenticate_aes fail: %04X", ret);
		return 5;
	}
//6. READ first 40 bits of data from Credential application.
	uint8_t bFileNo = param->awc_file_no;
	uint8_t *data;
	uint16_t dlen = 0;
	uint8_t offset[3] = {0x00, 0x00, 0x00};
	uint8_t length[3] = {sizeof(access_grid_simple_t), 0x00, 0x00};
	ret = reader_mfdf_read_data(evid, PHAL_MFDFEVX_COMMUNICATION_ENC, 0, bFileNo, offset, length, &data, &dlen);
	if(ret){
		LOG2_ERR("reader_mfdf_read_data fail: %04X", ret);
		return 6;
	}

	LOG2_BUF_DBG("data:", data, 16);
	access_grid_simple_t *ag_simple = (access_grid_simple_t*)data;

	uint8_t nbytes = ag_simple->nbits / 8;
	if(ag_simple->nbits & 0x07){
		nbytes++;
	}
	cred->nbit = ag_simple->nbits;
	cred->clen = nbytes;
	memcpy(cred->credential, ag_simple->data, nbytes);
	cred->credential[0] = 0;		//第一字节是sitecode，剩余的才是卡号。
	cred->tag.type = HFTAG_ACCESS_GRID;

	uint8_t end_apdu[] = {0x90, 0xee, 0x00, 0x00, 0x00};
	uint8_t *end_rapdu;
	uint16_t end_rlen;
	phpalI14443p4_Exchange(&gphNfcLib_Params.spalI14443p4, PH_EXCHANGE_DEFAULT, end_apdu, sizeof(end_apdu), &end_rapdu, &end_rlen);
//7. DESELECT credential.
	phpalI14443p4_Deselect(&gphNfcLib_Params.spalI14443p4);

	return 0;
}


int reader_read_ag_tag(Reader_T* read, credential_t* cred){
	int ret;
	ret = reader_read_ag_kg(&config_param.access_grid, cred);
	if(ret){
		LOG2_ERR("reader_read_ag_kg fail: %04X", ret);
		return ret;
	}

	return 0;
}

//初始化access grid
int reader_init_access_grid(void){
	int ret;
	//是否支持se
	if(!samav3_is_ready() || !reader_se_support()){
		LOG2_PRINT("SAM AV3 not found!");
		return -1;
	}	
	//装载Access Grid APPLE READ密钥
	LOG2_PRINT("\nAccess Grid APPLE READ key loading: ");
	ret = samav3_load_default_key(SAM_KID_ACCESS_GRID_APPLE_READ, cfg_key_default.access_grid_apple_read.data, 1, SAM_KEY_CLASS_PICC, SAM_KEY_T_AES_128, 1);
	if(ret < 0) {
		LOG2_PRINT("Failed to load Access Grid APPLE READ key: %d\n", ret);
	}
	else {
		LOG2_PRINT("Load Access Grid APPLE READ key successful!");
	}
	//装载Access Grid APPLE PRIVACY密钥
	LOG2_PRINT("\nAccess Grid APPLE PRIVACY key loading: ");
	ret = samav3_load_default_key(SAM_KID_ACCESS_GRID_APPLE_PRIVACY, cfg_key_default.access_grid_apple_privacy.data, 1, SAM_KEY_CLASS_PICC, SAM_KEY_T_AES_128, 1);
	if(ret < 0) {
		LOG2_PRINT("Failed to load Access Grid APPLE PRIVACY key: %d\n", ret);
	}
	else {
		LOG2_PRINT("Load Access Grid APPLE PRIVACY key successful!");
	}
	return ret;
}

/***********************************************************************************************
*                            End Of File
**********************************************************************************************/

